<?php

declare(strict_types=1);

namespace Zlf\Enums;

use Zlf\Unit\Arr;

trait EnumsTrait
{

    public static function Enum(mixed $value, ?string $tag = null): ?array
    {
        $enums = self::getEnums($tag);
        foreach ($enums as $item) {
            if ($item['value'] === $value) {
                return Arr::merge(['value' => $item['value'], 'label' => $item['label']], $item['arg'] ?? []);
            }
        }
        return null;
    }

    /**
     * 解释枚举值含义
     * @param mixed $value
     * @param string|null $tag
     * @return mixed|null
     */
    final public static function Explain(mixed $value, ?string $tag = null): mixed
    {
        $enums = self::getEnums($tag);
        foreach ($enums as $item) {
            if ($item['value'] === $value) {
                return $item['label'];
            }
        }
        return null;
    }


    /**
     * 检测是否属于定义的枚举值
     * @param mixed $value
     * @param string|null $tag
     * @return bool
     */
    final public static function Exists(mixed $value, ?string $tag = null): bool
    {
        $enums = self::getEnums($tag);
        foreach ($enums as $item) {
            if ($item['value'] === $value) {
                return true;
            }
        }
        return false;
    }


    /**
     * 获取所哟枚举值
     * @param string|null $tag
     * @param bool $toString
     * @return array
     */
    final public static function Values(?string $tag = null, bool $toString = true): array
    {
        $values = [];
        foreach (self::getEnums($tag) as $enum) {
            if ($toString) {
                $values[] = (string)$enum['value'];
            } else {
                $values[] = $enum['value'];
            }
        }
        return $values;
    }


    /**
     * 获取所哟枚举值
     * @param string|null $tag
     * @return array
     */
    final public static function ValuesToData(?string $tag = null): array
    {
        $list = [];
        foreach (self::Datas($tag) as $value) {
            $list[] = [
                'value' => $value['value'], 'label' => self::Explain($value['value'], $tag)
            ];
        }
        return $list;
    }


    /**
     * 获取所有的解释值
     * @param ?string $tag
     * @return array
     */
    final public static function Labels(?string $tag = null): array
    {
        $label = [];
        foreach (self::getEnums($tag) as $enum) {
            $label[] = $enum['label'];
        }
        return $label;
    }


    /**
     * 获取表单数据
     * @param string|null $tag
     * @param bool $toString
     * @return array
     */
    final public static function Datas(?string $tag = null, bool $toString = false): array
    {
        foreach (self::getEnums($tag) as $item) {
            $item['arg'] = $item['arg'] ?? [];
            if ($toString) {
                $data[] = Arr::merge(['value' => (string)$item['value'], 'label' => $item['label']], $item['arg']);
            } else {
                $data[] = Arr::merge(['value' => $item['value'], 'label' => $item['label']], $item['arg']);
            }
        }
        return $data;
    }


    /**
     * 获取键值对数据数组
     * @param string|null $tag
     * @return array
     */
    final public static function Map(?string $tag = null): array
    {
        $map = [];
        foreach (self::getEnums($tag) as $item) {
            $map[$item['value']] = $item['label'];
        }
        return $map;
    }


    /**
     * 通过label获取value
     * @param string $label
     * @param string|null $tag
     * @return mixed
     */
    final public static function LabelByValue(string $label, ?string $tag = null): mixed
    {
        foreach (self::getEnums($tag) as $item) {
            if ($item['label'] === $label) {
                return $item['value'];
            }
        }
        return null;
    }


    /**
     * 获取枚举数据
     * @param string|null $tag
     * @return array
     */
    private static function getEnums(?string $tag = null): array
    {
        $annotate = Annotate::getClassAnnotate(static::class);
        $enums = [];
        foreach ($annotate['constant'] as $item) {
            $enum = $item[Enums::class] ?? null;
            if (is_null($enum)) continue;
            if ($tag === ($enum['tag'] ?? null) || is_null($tag)) {
                $enums[] = $enum;
            }
        }
        return $enums;
    }
}